(define map
  (native_function "
    Proc.new do |arguments, interpreter|
      list = interpreter.evaluate(arguments[0])
      formals = arguments[1]
      body = arguments.slice(2, arguments.length)

      raise 'Error: Map function takes a minimum of three arguments!' unless arguments.length > 2
      raise 'Error: Argument one must be a list!' unless list.is_a? Array
      raise 'Error: Formal cannot be defined as a string!' if formals.is_a? String
      
      if formals.is_a? Array
        raise 'Error: Map function takes one formal!' if formals.length != 1
        formals = formals[0]
      end

      sub_env = Schaefer::Environment.new(interpreter.current_environment)
     
      executeList = Proc.new do |body, environment, interpreter|
        interpreter.current_environment = environment
        result = []
        list.each do |element|
          interpreter.current_environment.define(formals, element)
          body.each do |expression|
            result << interpreter.evaluate(expression) 
          end
        end
        interpreter.current_environment = environment.parent
        result
      end
      
      executeList.call(body, sub_env, interpreter) 
    end
  "))
